﻿//using System;
//using System.Collections.Generic;
//using System.IO;
//using System.Linq;
//using System.Reflection;
//using System.ServiceModel;
//using System.Text;
//using LinFu.IoC.Configuration;
//using LinFu.IoC.Interfaces;
//using LinFu.IoC.Configuration;
//using Mono.Cecil;
//using LinFu.Reflection.Emit;
//using CoreEx.Common.Extensions;
//using TypeAttributes=Mono.Cecil.TypeAttributes;

//namespace CoreEx.Wcf.Common.Implementation
//{
//    [Implements(typeof(IServiceContractFactory),LifecycleType.Singleton)]
//    public class ServiceContractFactory : IServiceContractFactory ,IInitialize
//    {
//        private IServiceContainer _serviceContainer;
//        private static readonly IDictionary<Type,Type> _cache = new Dictionary<Type, Type>();
//        private static IDictionary<string, Assembly> _dynamicAssemblies = new Dictionary<string, Assembly>();
       

//        public Type CreateServiceContract(Type type)
//        {
//            if (!_cache.ContainsKey(type))
//            {
//                AssemblyDefinition sourceAssembly =
//                    AssemblyFactory.GetAssembly(new Uri(type.Assembly.CodeBase).LocalPath);

                
                

//                var sourceTypeDefinition = sourceAssembly.MainModule.Types.Cast<TypeDefinition>().Where(t => t.Name == type.Name).FirstOrDefault();

                

//                var targetTypeDefinition = sourceTypeDefinition.Clone();
//                targetTypeDefinition.Namespace = "TEST";
//                var targetAssemblyName = "MyAssembly" + Guid.NewGuid().ToString();                
//                var targetAssembly = AssemblyFactory.DefineAssembly(targetAssemblyName, AssemblyKind.Dll);



//                //targetAssembly.MainModule.Types.Add(target);

//                targetAssembly.MainModule.AssemblyReferences.Add(sourceAssembly.Name);

                

//                //targetAssembly.SecurityDeclarations.Add(new SecurityDeclaration(SecurityAction.RequestMinimum));
//                var test = sourceAssembly.MainModule.AssemblyReferences.Cast<AssemblyNameReference>();

//                test.ForEach(a => targetAssembly.MainModule.AssemblyReferences.Add(a));
                

//                if (!type.HasAttribute(typeof(ServiceContractAttribute)))
//                {
//                    var serviceContractConstructor = targetAssembly.MainModule.Import(
//                        typeof (ServiceContractAttribute).GetConstructor(new Type[] {}));

//                    var serviceContractAttribute = new CustomAttribute(serviceContractConstructor);
//                    targetTypeDefinition.CustomAttributes.Add(serviceContractAttribute);
//                }

                
                
                
//                var operationContractConstructor = targetAssembly.MainModule.Import(
//                    typeof(OperationContractAttribute).GetConstructor(new Type[] { }));
//                var serviceMethods = type.GetMethods();

//                var targetMethods = targetTypeDefinition.Methods.Cast<MethodDefinition>()
//                    .Join(serviceMethods, methodDefinitiion => methodDefinitiion.Name, methodInfo
//                                                                                       => methodInfo.Name,
//                          (methodDefinition, methodInfo) => new { methodDefinition, methodInfo });


//                foreach (var targetMethod in targetMethods)
//                {
//                    if (!targetMethod.methodInfo.HasAttribute(typeof(OperationContractAttribute)))
//                    {
//                        var operationContractAttribute = new CustomAttribute(operationContractConstructor);
//                        TypeReference stringType = targetAssembly.MainModule.Import(typeof (string));
//                        operationContractAttribute.SetPropertyType("Name", stringType);
//                        operationContractAttribute.Properties.Add("Name",string.Format("{0}.{1}",type.FullName,targetMethod.methodInfo.Name));

//                        operationContractAttribute.SetPropertyType("Action", stringType);
//                        operationContractAttribute.Properties.Add("Action", string.Format("{0}.{1}", type.FullName, targetMethod.methodInfo.Name));
                        
//                        operationContractAttribute.SetPropertyType("ReplyAction", stringType);
//                        operationContractAttribute.Properties.Add("ReplyAction", string.Format("{0}.ResponseTo{1}", type.FullName, targetMethod.methodInfo.Name));
//                        targetMethod.methodDefinition.CustomAttributes.Add(operationContractAttribute);                        
//                    }
//                }


//                targetTypeDefinition.Name = "Bernhard";

//                // targetAssembly.MainModule.Inject(targetTypeDefinition);

                

//                //targetAssembly.MainModule.Types.Add(targetTypeDefinition);


//                MemoryStream memoryStream = new MemoryStream();
                
//                AssemblyFactory.SaveAssembly(targetAssembly, memoryStream);
//                var buffer = memoryStream.GetBuffer();

//                try
//                {
//                    Assembly serviceAssembly = Assembly.Load(buffer);
//                    _cache.Add(type, serviceAssembly.GetTypes().First());

//                    _dynamicAssemblies.Add(serviceAssembly.GetName().FullName, serviceAssembly);
//                }
//                catch (Exception ex)
//                {
                    
//                    throw;
//                }
                
//            }

//            return _cache[type];
            
//        }

//        public Type CreateServiceContract(Type type, bool createAttributes)
//        {
//            throw new System.NotImplementedException();
//        }

//        public void Initialize(IServiceContainer source)
//        {
//            _serviceContainer = source;

//            AppDomain.CurrentDomain.AssemblyResolve += (CurrentDomain_AssemblyResolve);            
//        }

//        Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
//        {
//            if (_dynamicAssemblies.ContainsKey(args.Name))
//                return _dynamicAssemblies[args.Name];
//            return null;
//        }
//    }
//}